package com.liannong.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liannong.entity.Warehouse;
import com.liannong.entity.Product;
import com.liannong.exception.BusinessException;
import com.liannong.mapper.WarehouseMapper;
import com.liannong.mapper.ProductMapper;
import com.liannong.service.WarehouseService;
import com.liannong.vo.WarehouseVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;

@Service
public class WarehouseServiceImpl extends ServiceImpl<WarehouseMapper, Warehouse> implements WarehouseService {

    private static final Logger log = LoggerFactory.getLogger(WarehouseServiceImpl.class);

    @Autowired
    private WarehouseMapper warehouseMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 系统启动时初始化库存缓存
     */
    @PostConstruct
    public void initAmountCache() {
        List<Warehouse> warehouses = list();
        for (Warehouse warehouse : warehouses) {
            String key = "product:amount:" + warehouse.getProductId();
            redisTemplate.opsForValue().set(key, String.valueOf(warehouse.getAmount().intValue()), 24, TimeUnit.HOURS);
        }
    }

    @Override
    public List<WarehouseVO> getWarehouseList() {
        log.info("开始查询所有仓库记录");
        try {
            List<Warehouse> warehouses = this.list();
            log.info("从数据库查询到 {} 条仓库记录", warehouses.size());
            
            if (!warehouses.isEmpty()) {
                log.info("第一条记录信息: id={}, traceCode={}, name={}", 
                        warehouses.get(0).getId(),
                        warehouses.get(0).getTraceCode(),
                        warehouses.get(0).getName());
            }
            
            List<WarehouseVO> result = warehouses.stream()
                    .map(this::convertToWarehouseVO)
                    .collect(Collectors.toList());
            log.info("转换后的VO对象数量: {}", result.size());
            return result;
        } catch (Exception e) {
            log.error("查询所有仓库记录失败", e);
            throw e;
        }
    }

    @Override
    public WarehouseVO getWarehouseDetail(Integer warehouseId) {
        log.info("开始查询仓库详情: warehouseId={}", warehouseId);
        try {
            Warehouse warehouse = this.getById(warehouseId);
            if (warehouse == null) {
                log.warn("未找到仓库记录: warehouseId={}", warehouseId);
                throw new BusinessException("仓库不存在");
            }
            log.info("查询到仓库记录: id={}, traceCode={}, name={}", 
                    warehouse.getId(), 
                    warehouse.getTraceCode(), 
                    warehouse.getName());
            return convertToWarehouseVO(warehouse);
        } catch (Exception e) {
            log.error("查询仓库详情失败: warehouseId={}", warehouseId, e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateTemperature(Integer id, Integer temperature) {
        log.info("开始更新仓库温度: id={}, temperature={}", id, temperature);
        try {
            Warehouse warehouse = this.getById(id);
            if (warehouse == null) {
                log.warn("未找到仓库记录: id={}", id);
                throw new BusinessException("仓库记录不存在");
            }
            
            warehouse.setNowTemp(temperature);
            boolean result = this.updateById(warehouse);
            log.info("更新仓库温度结果: {}", result);
            return result;
        } catch (Exception e) {
            log.error("更新仓库温度失败: id={}, temperature={}", id, temperature, e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateSendDate(Integer id, LocalDate sendDate) {
        Warehouse warehouse = this.getById(id);
        if (warehouse == null) {
            throw new BusinessException("仓库记录不存在");
        }
        
        warehouse.setSendDate(sendDate);
        return this.updateById(warehouse);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRecvDate(Integer id, LocalDate recvDate) {
        Warehouse warehouse = this.getById(id);
        if (warehouse == null) {
            throw new BusinessException("仓库记录不存在");
        }
        
        warehouse.setRecvDate(recvDate);
        return this.updateById(warehouse);
    }

    @Override
    public Warehouse getByTraceCode(String traceCode) {
        log.info("开始根据溯源码查询仓库记录: traceCode={}", traceCode);
        try {
            QueryWrapper<Warehouse> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("traceCode", traceCode);
            Warehouse warehouse = this.getOne(queryWrapper);
            if (warehouse != null) {
                log.info("查询到仓库记录: id={}, name={}", warehouse.getId(), warehouse.getName());
            } else {
                log.warn("未找到仓库记录: traceCode={}", traceCode);
            }
            return warehouse;
        } catch (Exception e) {
            log.error("根据溯源码查询仓库记录失败: traceCode={}", traceCode, e);
            throw e;
        }
    }

    @Override
    public boolean checkProductExists(Long productId) {
        log.info("检查商品是否存在: productId={}", productId);
        try {
            if (productId == null) {
                return false;
            }
            // 查询商品表
            Product product = productMapper.selectById(productId);
            boolean exists = product != null;
            log.info("商品{}存在", exists ? "" : "不");
            return exists;
        } catch (Exception e) {
            log.error("检查商品是否存在失败: productId={}", productId, e);
            return false;
        }
    }

    @Override
    public boolean checkProductStockExists(Long productId) {
        log.info("检查商品是否已有库存记录: productId={}", productId);
        try {
            if (productId == null) {
                return false;
            }
            // 查询仓库表中是否有该商品的记录
            QueryWrapper<Warehouse> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("product_id", productId);
            Warehouse warehouse = this.getOne(queryWrapper);
            boolean exists = warehouse != null;
            log.info("商品库存记录{}存在", exists ? "" : "不");
            return exists;
        } catch (Exception e) {
            log.error("检查商品是否已有库存记录失败: productId={}", productId, e);
            return false;
        }
    }

    @Override
    public List<Warehouse> getByName(String name) {
        log.info("开始根据产品名称查询仓库记录: name={}", name);
        try {
            QueryWrapper<Warehouse> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name", name);
            List<Warehouse> warehouseList = this.list(queryWrapper);
            log.info("查询到仓库记录数: {}", warehouseList.size());
            return warehouseList;
        } catch (Exception e) {
            log.error("根据产品名称查询仓库记录失败: name={}", name, e);
            throw e;
        }
    }

    @Override
    public boolean checkWarehouseAvailable(Integer warehouseId) {
        Warehouse warehouse = this.getById(warehouseId);
        if (warehouse == null) {
            throw new BusinessException("仓库不存在");
        }
        
        return true;
    }
    
    @Override
    public boolean addWarehouse(Warehouse warehouse) {
        return this.save(warehouse);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWarehouseAmount(Long productId, int newAmount) {
        log.info("开始更新仓库库存: productId={}, newAmount={}", productId, newAmount);
        try {
            // 先根据商品ID查询
            QueryWrapper<Warehouse> productIdQuery = new QueryWrapper<>();
            productIdQuery.eq("product_id", productId);
            Warehouse warehouse = this.getOne(productIdQuery);
            
            // 如果没找到，尝试用traceCode查询
            if (warehouse == null) {
                QueryWrapper<Warehouse> traceCodeQuery = new QueryWrapper<>();
                traceCodeQuery.eq("traceCode", productId.toString());
                warehouse = this.getOne(traceCodeQuery);
            }
            
            if (warehouse == null) {
                log.warn("未找到对应的仓库记录, 准备创建新记录: productId={}", productId);
                // 如果记录不存在，创建新记录
                warehouse = new Warehouse();
                warehouse.setTraceCode(productId.toString());
                warehouse.setProductId(productId); // 设置关联的商品ID
                warehouse.setAmount(new java.math.BigDecimal(newAmount));
                
                // 设置必填字段的默认值
                warehouse.setOrigin("未知"); // 必填字段
                warehouse.setName("商品" + productId); // 必填字段
                
                // 尝试从products表获取更多信息
                try {
                    // 这里假设有一个productMapper可以获取商品信息
                    Product product = productMapper.selectById(productId);
                    if (product != null) {
                        warehouse.setName(product.getName());
                        warehouse.setOrigin(product.getOrigin() != null ? product.getOrigin() : "未知");
                    }
                } catch (Exception e) {
                    log.warn("获取商品信息失败", e);
                }
                
                int insertResult = warehouseMapper.insert(warehouse);
                log.info("创建新仓库记录结果: {}, id={}", insertResult > 0, warehouse.getId());
                
                if (insertResult <= 0) {
                    throw new BusinessException("创建仓库记录失败");
                }
            } else {
                log.info("找到仓库记录, 准备更新: id={}, oldAmount={}, newAmount={}", 
                        warehouse.getId(), 
                        warehouse.getAmount(), 
                        newAmount);
                
                // 确保productId字段已设置
                if (warehouse.getProductId() == null) {
                    warehouse.setProductId(productId);
                }
                
                // 更新现有记录
                warehouse.setAmount(new java.math.BigDecimal(newAmount));
                int updateResult = warehouseMapper.updateById(warehouse);
                log.info("更新仓库记录结果: {}", updateResult > 0);
                
                if (updateResult <= 0) {
                    throw new BusinessException("更新仓库记录失败");
                }
            }
            
            // 验证更新是否成功
            QueryWrapper<Warehouse> verifyQuery = new QueryWrapper<>();
            verifyQuery.eq("product_id", productId);
            warehouse = this.getOne(verifyQuery);
            if (warehouse == null) {
                // 尝试用traceCode查询
                QueryWrapper<Warehouse> traceCodeQuery = new QueryWrapper<>();
                traceCodeQuery.eq("traceCode", productId.toString());
                warehouse = this.getOne(traceCodeQuery);
            }
            
            if (warehouse == null) {
                log.error("验证更新失败，未找到仓库记录: productId={}", productId);
                throw new BusinessException("验证更新失败，未找到仓库记录");
            }
            
            log.info("验证更新结果: id={}, amount={}, 期望值={}, 是否一致={}", 
                    warehouse.getId(), 
                    warehouse.getAmount(), 
                    newAmount,
                    warehouse.getAmount().intValue() == newAmount);
        } catch (Exception e) {
            log.error("更新仓库库存失败: productId={}, newAmount={}", productId, newAmount, e);
            throw new BusinessException("更新仓库库存失败: " + e.getMessage());
        }
    }
    
    /**
     * 为现有仓库记录关联商品ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void linkWarehouseToProducts() {
        log.info("开始关联仓库记录与商品ID");
        try {
            // 获取所有未关联商品ID的仓库记录
            QueryWrapper<Warehouse> queryWrapper = new QueryWrapper<>();
            queryWrapper.isNull("product_id").isNotNull("traceCode");
            List<Warehouse> warehouses = this.list(queryWrapper);
            
            if (warehouses.isEmpty()) {
                log.info("没有需要关联的仓库记录");
                return;
            }
            
            log.info("找到{}条需要关联的仓库记录", warehouses.size());
            
            int successCount = 0;
            int failCount = 0;
            
            for (Warehouse warehouse : warehouses) {
                String traceCode = warehouse.getTraceCode();
                try {
                    // 根据traceCode查询商品
                    QueryWrapper<Product> productQuery = new QueryWrapper<>();
                    productQuery.eq("traceCode", traceCode);
                    Product product = productMapper.selectOne(productQuery);
                    
                    if (product != null) {
                        // 更新warehouse记录
                        warehouse.setProductId((long)product.getProductId());
                        boolean success = this.updateById(warehouse);
                        if (success) {
                            successCount++;
                            log.info("成功关联仓库记录: id={}, traceCode={}, productId={}", 
                                    warehouse.getId(), traceCode, product.getProductId());
                        } else {
                            failCount++;
                            log.warn("关联仓库记录失败: id={}, traceCode={}", warehouse.getId(), traceCode);
                        }
                    } else {
                        log.warn("未找到对应的商品记录: traceCode={}", traceCode);
                        failCount++;
                    }
                } catch (Exception e) {
                    log.error("关联仓库记录时出错: id={}, traceCode={}", warehouse.getId(), traceCode, e);
                    failCount++;
                }
            }
            
            log.info("关联仓库记录完成: 成功={}, 失败={}", successCount, failCount);
        } catch (Exception e) {
            log.error("关联仓库记录失败", e);
            throw new BusinessException("关联仓库记录失败: " + e.getMessage());
        }
    }
    
    /**
     * 创建新的仓库记录
     * @param productId 商品ID
     * @param amount 数量
     * @param origin 原产地
     * @param name 商品名称
     * @param nowTemp 当前温度
     * @return 创建的仓库记录
     */
    @Transactional(rollbackFor = Exception.class)
    public Warehouse createWarehouse(Long productId, BigDecimal amount, String origin, String name, Integer nowTemp) {
        log.info("开始创建仓库记录: productId={}, amount={}", productId, amount);
        try {
            // 检查商品是否存在
            Product product = productMapper.selectById(productId);
            if (product == null) {
                log.error("商品不存在: productId={}", productId);
                throw new BusinessException("商品不存在: productId=" + productId);
            }
            
            // 检查是否已存在该商品的仓库记录
            boolean stockExists = checkProductStockExists(productId);
            if (stockExists) {
                log.warn("商品已存在仓库记录: productId={}", productId);
                throw new BusinessException("商品已存在仓库记录");
            }
            
            // 创建新记录
            Warehouse warehouse = new Warehouse();
            warehouse.setProductId(productId);
            
            // 优先使用商品的溯源码
            if (product.getTraceCode() != null && !product.getTraceCode().isEmpty()) {
                warehouse.setTraceCode(product.getTraceCode());
            } else {
                // 如果商品没有溯源码，使用商品ID作为溯源码
                warehouse.setTraceCode(productId.toString());
            }
            
            // 设置数量
            warehouse.setAmount(amount);
            
            // 设置原产地
            if (origin != null && !origin.isEmpty()) {
                warehouse.setOrigin(origin);
            } else if (product.getOrigin() != null && !product.getOrigin().isEmpty()) {
                warehouse.setOrigin(product.getOrigin());
            } else {
                warehouse.setOrigin("未知");
            }
            
            // 设置商品名称
            if (name != null && !name.isEmpty()) {
                warehouse.setName(name);
            } else if (product.getName() != null && !product.getName().isEmpty()) {
                warehouse.setName(product.getName());
            } else {
                warehouse.setName("商品" + productId);
            }
            
            // 设置温度
            if (nowTemp != null) {
                warehouse.setNowTemp(nowTemp);
            } else {
                // 使用商品推荐温度作为默认值
                Integer defaultTemp = (product.getMinTemp() != null && product.getMaxTemp() != null) ? 
                        (product.getMinTemp() + product.getMaxTemp()) / 2 : 0;
                warehouse.setNowTemp(defaultTemp);
            }
            
            int insertResult = warehouseMapper.insert(warehouse);
            
            if (insertResult <= 0) {
                log.error("创建仓库记录失败");
                throw new BusinessException("创建仓库记录失败");
            }
            
            log.info("创建仓库记录成功: id={}, productId={}", warehouse.getId(), productId);
            return warehouse;
        } catch (BusinessException e) {
            log.error("创建仓库记录失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("创建仓库记录失败", e);
            throw new BusinessException("创建仓库记录失败: " + e.getMessage());
        }
    }
    
    @Override
    public int getWarehouseAmount(Long productId) {
        // 优先从Redis获取库存
        String key = "product:amount:" + productId;
        String amountStr = redisTemplate.opsForValue().get(key);
        
        if (amountStr != null) {
            return Integer.parseInt(amountStr);
        }
        
        // Redis中没有，从数据库获取并缓存
        QueryWrapper<Warehouse> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id", productId);
        Warehouse warehouse = warehouseMapper.selectOne(queryWrapper);
        
        int amount = warehouse != null ? warehouse.getAmount().intValue() : 0;
        
        // 缓存到Redis
        redisTemplate.opsForValue().set(key, String.valueOf(amount), 24, TimeUnit.HOURS);
        
        return amount;
    }

    @Override
    public Product getProductInfo(Long productId) {
        log.info("获取商品信息: productId={}", productId);
        try {
            if (productId == null) {
                return null;
            }
            // 查询商品表
            Product product = productMapper.selectById(productId);
            if (product != null) {
                log.info("查询到商品信息: id={}, name={}, traceCode={}", 
                    product.getProductId(), product.getName(), product.getTraceCode());
            } else {
                log.warn("未找到商品信息: productId={}", productId);
            }
            return product;
        } catch (Exception e) {
            log.error("获取商品信息失败: productId={}", productId, e);
            return null;
        }
    }

    /**
     * 同步Redis库存到数据库
     * @param productId 商品ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void syncAmountToDb(Long productId) {
        String key = "product:amount:" + productId;
        String amountStr = redisTemplate.opsForValue().get(key);
        
        if (amountStr != null) {
            int amount = Integer.parseInt(amountStr);
            
            QueryWrapper<Warehouse> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("product_id", productId);
            Warehouse warehouse = warehouseMapper.selectOne(queryWrapper);
            
            if (warehouse != null) {
                warehouse.setAmount(new java.math.BigDecimal(amount));
                updateById(warehouse);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWarehouseAmountByTraceCode(String traceCode, int newAmount) {
        log.info("根据溯源码更新库存: traceCode={}, newAmount={}", traceCode, newAmount);
        
        if (traceCode == null || traceCode.trim().isEmpty()) {
            log.error("溯源码为空");
            return false;
        }
        
        try {
            // 根据溯源码查询仓库记录
            Warehouse warehouse = getByTraceCode(traceCode);
            
            if (warehouse == null) {
                log.warn("未找到溯源码对应的仓库记录: {}", traceCode);
                
                // 尝试根据溯源码查找商品，以获取商品ID
                QueryWrapper<Product> productQuery = new QueryWrapper<>();
                productQuery.eq("traceCode", traceCode);
                Product product = productMapper.selectOne(productQuery);
                
                if (product == null || product.getProductId() == null) {
                    log.error("未找到溯源码对应的商品信息: {}", traceCode);
                    return false;
                }
                
                // 使用商品ID更新库存
                log.info("找到商品: id={}, 现在使用商品ID更新库存", product.getProductId());
                updateWarehouseAmount(product.getProductId().longValue(), newAmount);
                return true;
            } else {
                // 直接更新仓库记录
                warehouse.setAmount(new BigDecimal(newAmount));
                log.info("更新仓库记录库存: id={}, traceCode={}, newAmount={}", warehouse.getId(), traceCode, newAmount);
                
                // 如果有商品ID，同时更新缓存
                if (warehouse.getProductId() != null) {
                    String key = "product:amount:" + warehouse.getProductId();
                    redisTemplate.opsForValue().set(key, String.valueOf(newAmount), 24, TimeUnit.HOURS);
                    log.info("更新了productId={}的库存缓存", warehouse.getProductId());
                }
                
                // 更新数据库
                return this.updateById(warehouse);
            }
        } catch (Exception e) {
            log.error("根据溯源码更新库存失败: traceCode={}", traceCode, e);
            throw new BusinessException("更新库存失败: " + e.getMessage());
        }
    }

    private WarehouseVO convertToWarehouseVO(Warehouse warehouse) {
        if (warehouse == null) {
            log.warn("尝试转换null的Warehouse对象");
            return null;
        }
        
        try {
            WarehouseVO vo = new WarehouseVO();
            vo.setId(warehouse.getId());
            vo.setWarehouseId(warehouse.getId());
            vo.setTraceCode(warehouse.getTraceCode());
            vo.setAmount(warehouse.getAmount());
            vo.setSendDate(warehouse.getSendDate());
            vo.setOrigin(warehouse.getOrigin());
            vo.setName(warehouse.getName());
            vo.setProductName(warehouse.getName());
            vo.setRecvDate(warehouse.getRecvDate());
            vo.setNowTemp(warehouse.getNowTemp());
            vo.setCurrentTemperature(warehouse.getNowTemp());
            
            if (warehouse.getRecvDate() != null) {
                vo.setStatus("3");
            } else if (warehouse.getSendDate() != null) {
                vo.setStatus("2");
            } else {
                vo.setStatus("1");
            }
            
            return vo;
        } catch (Exception e) {
            log.error("转换WarehouseVO失败: id={}", warehouse.getId(), e);
            throw e;
        }
    }
} 